*DECK DRMGEN
      SUBROUTINE DRMGEN (NELTMX, FACTOR, IERR, N, NELT, ISYM, IA, JA, A,
     $   F, SOLN, DSUM, ITMP, IDIAG)
C***BEGIN PROLOGUE  DRMGEN
C***SUBSIDIARY
C***PURPOSE  This routine generates a "Random" symmetric or
C            non-symmetric matrix of size N for use in the SLAP
C            Quick Checks.
C***LIBRARY   SLATEC (SLAP)
C***TYPE      DOUBLE PRECISION (SRMGEN-S, DRMGEN-D)
C***AUTHOR  Seager, Mark K., (LLNL)
C             seager@llnl.gov
C             Lawrence Livermore National Laboratory
C             PO BOX 808, L-300
C             Livermore, CA 94550
C             (510) 423-3141
C***DESCRIPTION
C
C *Usage:
C       INTEGER NELTMX, IERR, N, NELT, ISYM,
C       INTEGER IA(NELTMX), JA(NELTMX), ITMP(N), IDIAG(N)
C       DOUBLE PRECISION FACTOR, A(NELTMX), F(N), SOLN(N), DSUM(N)
C
C       CALL DRMGEN( NELTMX, FACTOR, IERR, N, NELT, ISYM,
C      $     IA, JA, A, F, SOLN, DSUM, ITMP, IDIAG )
C
C *Arguments:
C
C NELTMX :IN       Integer.
C         Maximum number of non-zeros that can be created by this
C         routine for storage in the IA, JA, A arrays,  see below.
C FACTOR :IN       Double Precision.
C         Non-zeros in the upper triangle are set to FACTOR times
C         the corresponding entry in the lower triangle when a non-
C         symmetric matrix is requested (See ISYM, below).
C IERR   :OUT      Integer.
C         Return error flag.
C             IERR = 0 => everything went OK.
C                  = 1 => Ran out of space trying to create matrix.
C                         Set NELTMX to something larger and retry.
C N      :IN       Integer.
C         Size of the linear system to generate (number of unknowns).
C NELT   :OUT      Integer.
C         Number of non-zeros stored in the IA, JA, A arrays, see below.
C ISYM   :IN       Integer.
C         Flag to indicate the type of matrix to generate:
C             ISYM = 0 => Non-Symmetric Matrix (See FACTOR, above).
C                  = 1 => Symmetric Matrix.
C IA     :OUT      Integer IA(NELTMX).
C         Stores the row indices for the non-zeros.
C JA     :OUT      Integer JA(NELTMX).
C         Stores the column indices for the non-zeros.
C A      :OUT      Double Precision A(NELTMX).
C         Stores the values of the non-zeros.
C F      :OUT      Double Precision F(N).
C         The right hand side of the linear system.  Obtained by
C         multiplying the matrix times SOLN, see below.
C SOLN   :OUT      Double Precision SOLN(N).
C         The true solution to the linear system.  Each component is
C         chosen at random (0.0<SOLN(I)<1.0, I=1,N)
C DSUM   :WORK     Double Precision DSUM(N).
C ITMP   :WORK     Integer ITMP(N).
C IDIAG  :WORK     Integer IDIAG(N).
C
C *Description
C         The matrix is generated by choosing a random number of
C         entries for each column and then chosing negative random
C         numbers for each off diagonal.   The diagonal elements
C         are chosen to be positive and large enough so the matrix
C         is slightly diagonally dominant.  The lower triangle of
C         the matrix is generated and if isym.eq.0 (all matrix elements
C         stored) the upper triangle elements are chosen so that they
C         are FACTOR times the corresponding lower triangular element.
C
C***ROUTINES CALLED  ISMPL, RAND
C***REVISION HISTORY  (YYMMDD)
C   881120  DATE WRITTEN
C   890919  Replaced DMPL with ISMPL.  (MKS)
C   890920  Minor changes to reduce single/double differences.  (FNF)
C   920511  Added complete declaration section.  (WRB)
C***END PROLOGUE  DRMGEN
C     .. Scalar Arguments ..
      DOUBLE PRECISION FACTOR
      INTEGER IERR, ISYM, N, NELT, NELTMX
C     .. Array Arguments ..
      DOUBLE PRECISION A(NELTMX), DSUM(N), F(N), SOLN(N)
      INTEGER IA(NELTMX), IDIAG(N), ITMP(N), JA(NELTMX)
C     .. Local Scalars ..
      REAL DUMMY
      INTEGER I, ICOL, INUM, IROW, ISEED, K, NL
C     .. External Functions ..
      REAL RAND
      EXTERNAL RAND
C     .. External Subroutines ..
      EXTERNAL ISMPL
C     .. Intrinsic Functions ..
      INTRINSIC INT
C***FIRST EXECUTABLE STATEMENT  DRMGEN
C
C     Start by setting the random number generator seed.  This is done
C     for reproducibility in debugging.
C
C     Remove the seed setting call for production testing.
C
C     Note:  Double precision version did not work properly with
C            certain compilers with literal arguments to RAND.
C
      DUMMY = 16381.0
      ISEED = RAND( DUMMY )
      IERR = 0
      DO 10 I = 1, N
         IDIAG(I) = 0
         DSUM(I) = -1.0D0
 10   CONTINUE
      DUMMY = 0.0
      NELT = 0
C
C     Set the matrix elements.
C     Loop over the columns.
C
CVD$ NOCONCUR
      DO 30 ICOL = 1, N
         NL = N+1-ICOL
C
C         To keep things sparse divide by two, three or four or ...
C
         INUM = (INT( RAND(DUMMY)*NL ) + 1)/3
         CALL ISMPL( NL, INUM, ITMP )
C
C         Set up this column (and row, if non-symmetric structure).
CVD$ NOVECTOR
CVD$ NOCONCUR
         DO 20 IROW = 1, INUM
            NELT = NELT + 1
            IF( NELT.GT.NELTMX ) THEN
               IERR = 1
               RETURN
            ENDIF
            IA(NELT) = N+1-ITMP(IROW)
            JA(NELT) = ICOL
            IF( IA(NELT).EQ.ICOL ) THEN
               IDIAG(ICOL) = NELT
            ELSE
               A(NELT) = -RAND(DUMMY)
               DSUM(ICOL) = DSUM(ICOL) + A(NELT)
               IF( ISYM.EQ.0 ) THEN
C
C         Copy this element into upper triangle.
C
                  NELT = NELT + 1
                  IF( NELT.GT.NELTMX ) THEN
                     IERR = 1
                     RETURN
                  ENDIF
                  IA(NELT) = ICOL
                  JA(NELT) = IA(NELT-1)
                  A(NELT)  = A(NELT-1)*FACTOR
                  DSUM(JA(NELT)) = DSUM(JA(NELT)) + A(NELT)
               ELSE
                  DSUM(IA(NELT)) = DSUM(IA(NELT)) + A(NELT)
               ENDIF
            ENDIF
 20      CONTINUE
         IF( IDIAG(ICOL).EQ.0 ) THEN
C
C           Add a diagonal to the column.
C
            NELT = NELT + 1
            IF( NELT.GT.NELTMX ) THEN
               IERR = 1
               RETURN
            ENDIF
            IDIAG(ICOL) = NELT
            A(NELT) = 0.0D0
            IA(NELT) = ICOL
            JA(NELT) = ICOL
         ENDIF
 30   CONTINUE
C
C         Clean up the diagonals.
C
CVD$ NODEPCHK
CLLL. OPTION ASSERT (NOHAZARD)
CDIR$ IVDEP
      DO 40 I = 1, N
         A(IDIAG(I)) = -1.0001D0*DSUM(I)
 40   CONTINUE
C
C         Set a random solution and determine the right-hand side.
C
CVD$ NOVECTOR
CVD$ NOCONCUR
      DO 50 I = 1, N
         SOLN(I) = RAND(DUMMY)
         F(I) = 0.0D0
 50   CONTINUE
C
CVD$ NOVECTOR
CVD$ NOCONCUR
      DO 60 K = 1, NELT
         F(IA(K)) = F(IA(K)) + A(K)*SOLN(JA(K))
         IF( ISYM.NE.0 .AND. IA(K).NE.JA(K) ) THEN
            F(JA(K)) = F(JA(K)) + A(K)*SOLN(IA(K))
         ENDIF
 60   CONTINUE
      RETURN
C------------- LAST LINE OF DRMGEN FOLLOWS ----------------------------
      END
